home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d982.lha / HWGRCS / HWGpatchP1_2_1.lha / patch-2.1 / src / util.c < prev    next >
C/C++ Source or Header  |  1993-12-18  |  11KB  |  452 lines

  1. #include "EXTERN.h"
  2. #include "common.h"
  3. #include "INTERN.h"
  4. #include "util.h"
  5. #include "backupfile.h"
  6.  
  7. void my_exit();
  8.  
  9. #ifndef HAVE_STRERROR
  10. static char *
  11. private_strerror (errnum)
  12.      int errnum;
  13. {
  14.   extern char *sys_errlist[];
  15.   extern int sys_nerr;
  16.  
  17.   if (errnum > 0 && errnum <= sys_nerr)
  18.     return sys_errlist[errnum];
  19.   return "Unknown system error";
  20. }
  21. #define strerror private_strerror
  22. #endif /* !HAVE_STRERROR */
  23.  
  24. /* Rename a file, copying it if necessary. */
  25.  
  26. int
  27. move_file(from,to)
  28. char *from, *to;
  29. {
  30.     char bakname[512];
  31.     Reg1 char *s;
  32.     Reg2 int i;
  33.     Reg3 int fromfd;
  34.  
  35.     /* to stdout? */
  36.  
  37.     if (strEQ(to, "-")) {
  38. #ifdef DEBUGGING
  39.         if (debug & 4)
  40.             say2("Moving %s to stdout.\n", from);
  41. #endif
  42.         fromfd = open(from, 0);
  43.         if (fromfd < 0)
  44.             pfatal2("internal error, can't reopen %s", from);
  45.         while ((i=read(fromfd, buf, sizeof buf)) > 0)
  46.             if (write(1, buf, i) != 1)
  47.                 pfatal1("write failed");
  48.         Close(fromfd);
  49.         return 0;
  50.     }
  51.  
  52.     if (origprae) {
  53.         Strcpy(bakname, origprae);
  54.         Strcat(bakname, to);
  55.     } else {
  56. #ifndef NODIR
  57.         char *backupname = find_backup_file_name(to);
  58.         if (backupname == (char *) 0)
  59.             fatal1("out of memory\n");
  60.         Strcpy(bakname, backupname);
  61.         free(backupname);
  62. #else /* NODIR */
  63.         Strcpy(bakname, to);
  64.         Strcat(bakname, simple_backup_suffix);
  65. #endif /* NODIR */
  66.     }
  67.  
  68.     if (stat(to, &filestat) == 0) {     /* output file exists */
  69.         dev_t to_device = filestat.st_dev;
  70.         ino_t to_inode  = filestat.st_ino;
  71.         char *simplename = bakname;
  72.  
  73.         for (s=bakname; *s; s++) {
  74.             if (*s == '/')
  75.                 simplename = s+1;
  76.         }
  77.         /* Find a backup name that is not the same file.
  78.            Change the first lowercase char into uppercase;
  79.            if that isn't sufficient, chop off the first char and try again.  */
  80.         while (stat(bakname, &filestat) == 0 &&
  81.                 to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  82.             /* Skip initial non-lowercase chars.  */
  83.             for (s=simplename; *s && !islower(*s); s++) ;
  84.             if (*s)
  85.                 *s = toupper(*s);
  86.             else
  87.                 Strcpy(simplename, simplename+1);
  88.         }
  89.         while (unlink(bakname) >= 0) ;  /* while() is for benefit of Eunice */
  90. #ifdef DEBUGGING
  91.         if (debug & 4)
  92.             say3("Moving %s to %s.\n", to, bakname);
  93. #endif
  94.         if (rename(to, bakname) < 0) {
  95.             say4("Can't backup %s, output is in %s: %s\n", to, from,
  96.                  strerror(errno));
  97.             return -1;
  98.         }
  99.         while (unlink(to) >= 0) ;
  100.     }
  101. #ifdef DEBUGGING
  102.     if (debug & 4)
  103.         say3("Moving %s to %s.\n", from, to);
  104. #endif
  105.     if (rename(from, to) < 0) {         /* different file system? */
  106.         Reg4 int tofd;
  107.  
  108.         tofd = creat(to, 0666);
  109.         if (tofd < 0) {
  110.             say4("Can't create %s, output is in %s: %s\n",
  111.               to, from, strerror(errno));
  112.             return -1;
  113.         }
  114.         fromfd = open(from, 0);
  115.         if (fromfd < 0)
  116.             pfatal2("internal error, can't reopen %s", from);
  117.         while ((i=read(fromfd, buf, sizeof buf)) > 0)
  118.             if (write(tofd, buf, i) != i)
  119.                 pfatal1("write failed");
  120.         Close(fromfd);
  121.         Close(tofd);
  122.     }
  123.     Unlink(from);
  124.     return 0;
  125. }
  126.  
  127. /* Copy a file. */
  128.  
  129. void
  130. copy_file(from,to)
  131. char *from, *to;
  132. {
  133.     Reg3 int tofd;
  134.     Reg2 int fromfd;
  135.     Reg1 int i;
  136.  
  137.     tofd = creat(to, 0666);
  138.     if (tofd < 0)
  139.         pfatal2("can't create %s", to);
  140.     fromfd = open(from, 0);
  141.     if (fromfd < 0)
  142.         pfatal2("internal error, can't reopen %s", from);
  143.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  144.         if (write(tofd, buf, i) != i)
  145.             pfatal2("write to %s failed", to);
  146.     Close(fromfd);
  147.     Close(tofd);
  148. }
  149.  
  150. /* Allocate a unique area for a string. */
  151.  
  152. char *
  153. savestr(s)
  154. Reg1 char *s;
  155. {
  156.     Reg3 char *rv;
  157.     Reg2 char *t;
  158.  
  159.     if (!s)
  160.         s = "Oops";
  161.     t = s;
  162.     while (*t++);
  163.     rv = malloc((MEM) (t - s));
  164.     if (rv == Nullch) {
  165.         if (using_plan_a)
  166.             out_of_mem = TRUE;
  167.         else
  168.             fatal1("out of memory\n");
  169.     }
  170.     else {
  171.         t = rv;
  172.         while (*t++ = *s++);
  173.     }
  174.     return rv;
  175. }
  176.  
  177. #if defined(lint) && defined(CANVARARG)
  178.  
  179. /*VARARGS ARGSUSED*/
  180. say(pat) char *pat; { ; }
  181. /*VARARGS ARGSUSED*/
  182. fatal(pat) char *pat; { ; }
  183. /*VARARGS ARGSUSED*/
  184. pfatal(pat) char *pat; { ; }
  185. /*VARARGS ARGSUSED*/
  186. ask(pat) char *pat; { ; }
  187.  
  188. #else
  189.  
  190. /* Vanilla terminal output (buffered). */
  191.  
  192. void
  193. say(pat,arg1,arg2,arg3)
  194. char *pat;
  195. long arg1,arg2,arg3;
  196. {
  197.     fprintf(stderr, pat, arg1, arg2, arg3);
  198.     Fflush(stderr);
  199. }
  200.  
  201. /* Terminal output, pun intended. */
  202.  
  203. void                            /* very void */
  204. fatal(pat,arg1,arg2,arg3)
  205. char *pat;
  206. long arg1,arg2,arg3;
  207. {
  208.     fprintf(stderr, "patch: **** ");
  209.     fprintf(stderr, pat, arg1, arg2, arg3);
  210.     my_exit(1);
  211. }
  212.  
  213. /* Say something from patch, something from the system, then silence . . . */
  214.  
  215. void                            /* very void */
  216. pfatal(pat,arg1,arg2,arg3)
  217. char *pat;
  218. long arg1,arg2,arg3;
  219. {
  220.     int errnum = errno;
  221.  
  222.     fprintf(stderr, "patch: **** ");
  223.     fprintf(stderr, pat, arg1, arg2, arg3);
  224.     fprintf(stderr, ": %s\n", strerror(errnum));
  225.     my_exit(1);
  226. }
  227.  
  228. /* Get a response from the user, somehow or other. */
  229.  
  230. void
  231. ask(pat,arg1,arg2,arg3)
  232. char *pat;
  233. long arg1,arg2,arg3;
  234. {
  235.     int ttyfd;
  236.     int r;
  237.     bool tty2 = isatty(2);
  238.  
  239.     Sprintf(buf, pat, arg1, arg2, arg3);
  240.     Fflush(stderr);
  241.     write(2, buf, strlen(buf));
  242.     if (tty2) {                         /* might be redirected to a file */
  243.         r = read(2, buf, sizeof buf);
  244.     }
  245.     else if (isatty(1)) {               /* this may be new file output */
  246.         Fflush(stdout);
  247.         write(1, buf, strlen(buf));
  248.         r = read(1, buf, sizeof buf);
  249.     }
  250. #ifdef _AMIGA
  251.     else if ((ttyfd = open("CONSOLE:", 2)) >= 0 && isatty(ttyfd)) {
  252. #else
  253.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  254. #endif
  255.                                         /* might be deleted or unwriteable */
  256.         write(ttyfd, buf, strlen(buf));
  257.         r = read(ttyfd, buf, sizeof buf);
  258.         Close(ttyfd);
  259.     }
  260.     else if (isatty(0)) {               /* this is probably patch input */
  261.         Fflush(stdin);
  262.         write(0, buf, strlen(buf));
  263.         r = read(0, buf, sizeof buf);
  264.     }
  265.     else {                              /* no terminal at all--default it */
  266.         buf[0] = '\n';
  267.         r = 1;
  268.     }
  269.     if (r <= 0)
  270.         buf[0] = 0;
  271.     else
  272.         buf[r] = '\0';
  273.     if (!tty2)
  274.         say1(buf);
  275. }
  276. #endif /* lint */
  277.  
  278. /* How to handle certain events when not in a critical region. */
  279.  
  280. void
  281. set_signals(reset)
  282. int reset;
  283. {
  284. #ifndef lint
  285.     static RETSIGTYPE (*hupval)(),(*intval)();
  286.  
  287.     if (!reset) {
  288. #ifndef _AMIGA
  289.         hupval = signal(SIGHUP, SIG_IGN);
  290. #endif
  291.         if (hupval != SIG_IGN)
  292.             hupval = (RETSIGTYPE(*)())my_exit;
  293.         intval = signal(SIGINT, SIG_IGN);
  294.         if (intval != SIG_IGN)
  295.             intval = (RETSIGTYPE(*)())my_exit;
  296.     }
  297. #ifndef _AMIGA
  298.     Signal(SIGHUP, hupval);
  299. #endif
  300.     Signal(SIGINT, intval);
  301. #endif
  302. }
  303.  
  304. /* How to handle certain events when in a critical region. */
  305.  
  306. void
  307. ignore_signals()
  308. {
  309. #ifndef lint
  310. #ifndef _AMIGA
  311.     Signal(SIGHUP, SIG_IGN);
  312. #endif
  313.     Signal(SIGINT, SIG_IGN);
  314. #endif
  315. }
  316.  
  317. /* Make sure we'll have the directories to create a file.
  318.    If `striplast' is TRUE, ignore the last element of `filename'.  */
  319.  
  320. void
  321. makedirs(filename,striplast)
  322. Reg1 char *filename;
  323. bool striplast;
  324. {
  325.     char tmpbuf[256];
  326.     Reg2 char *s = tmpbuf;
  327.     char *dirv[20];             /* Point to the NULs between elements.  */
  328.     Reg3 int i;
  329.     Reg4 int dirvp = 0;         /* Number of finished entries in dirv. */
  330.  
  331.     /* Copy `filename' into `tmpbuf' with a NUL instead of a slash
  332.        between the directories.  */
  333.     while (*filename) {
  334.         if (*filename == '/') {
  335.             filename++;
  336.             dirv[dirvp++] = s;
  337.             *s++ = '\0';
  338.         }
  339.         else {
  340.             *s++ = *filename++;
  341.         }
  342.     }
  343.     *s = '\0';
  344.     dirv[dirvp] = s;
  345.     if (striplast)
  346.         dirvp--;
  347.     if (dirvp < 0)
  348.         return;
  349.  
  350.     strcpy(buf, "mkdir");
  351.     s = buf;
  352.     for (i=0; i<=dirvp; i++) {
  353.         struct stat sbuf;
  354.  
  355.         if (stat(tmpbuf, &sbuf) && errno == ENOENT) {
  356.             while (*s) s++;
  357.             *s++ = ' ';
  358.             strcpy(s, tmpbuf);
  359.         }
  360.         *dirv[i] = '/';
  361.     }
  362.     if (s != buf)
  363.         system(buf);
  364. }
  365.  
  366. /* Make filenames more reasonable. */
  367.  
  368. char *
  369. fetchname(at,strip_leading,assume_exists)
  370. char *at;
  371. int strip_leading;
  372. int assume_exists;
  373. {
  374.     char *fullname;
  375.     char *name;
  376.     Reg1 char *t;
  377.     char tmpbuf[200];
  378.     int sleading = strip_leading;
  379.  
  380.     if (!at)
  381.         return Nullch;
  382.     while (isspace(*at))
  383.         at++;
  384. #ifdef DEBUGGING
  385.     if (debug & 128)
  386.         say4("fetchname %s %d %d\n",at,strip_leading,assume_exists);
  387. #endif
  388. #ifdef _AMIGA
  389.     if (strnEQ(at, "NIL:", 4))          /* so files can be created by diffing */
  390.         return Nullch;                  /*   against /dev/null. */
  391. #endif
  392.     if (strnEQ(at, "/dev/null", 9))     /* so files can be created by diffing */
  393.         return Nullch;                  /*   against /dev/null. */
  394.     name = fullname = t = savestr(at);
  395.  
  396.     /* Strip off up to `sleading' leading slashes and null terminate.  */
  397.     for (; *t && !isspace(*t); t++)
  398.         if (*t == '/')
  399.             if (--sleading >= 0)
  400.                 name = t+1;
  401.     *t = '\0';
  402.  
  403.     /* If no -p option was given (957 is the default value!),
  404.        we were given a relative pathname,
  405.        and the leading directories that we just stripped off all exist,
  406.        put them back on.  */
  407. #ifdef _AMIGA
  408.     if (strip_leading == 957 && name != fullname && !strchr(fullname, ':')) {
  409. #else
  410.     if (strip_leading == 957 && name != fullname && *fullname != '/') {
  411. #endif
  412.         name[-1] = '\0';
  413.         if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) {
  414.             name[-1] = '/';
  415.             name=fullname;
  416.         }
  417.     }
  418.  
  419.     name = savestr(name);
  420.     free(fullname);
  421.  
  422.     if (stat(name, &filestat) && !assume_exists) {
  423.         char *filebase = basename(name);
  424.         int pathlen = filebase - name;
  425.  
  426.         /* Put any leading path into `tmpbuf'.  */
  427.         strncpy(tmpbuf, name, pathlen);
  428.  
  429. #define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
  430.         if (   try("RCS/%s%s", filebase, RCSSUFFIX)
  431.             || try("RCS/%s"  , filebase,         0)
  432.             || try(    "%s%s", filebase, RCSSUFFIX)
  433.             || try("SCCS/%s%s", SCCSPREFIX, filebase)
  434.             || try(     "%s%s", SCCSPREFIX, filebase))
  435.           return name;
  436.         free(name);
  437.         name = Nullch;
  438.     }
  439.  
  440.     return name;
  441. }
  442.  
  443. char *
  444. xmalloc (size)
  445.      unsigned size;
  446. {
  447.   register char *p = (char *) malloc (size);
  448.   if (!p)
  449.     fatal("out of memory");
  450.   return p;
  451. }
  452.